import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.net.*;
import java.math.*;

public class Experiment {
	
	public void TestConnectionWithHttp (int numThread){
		ArrayList<String> ulrs = getURLs();
		int step = ulrs.size()/numThread;
		ConnectionWithHttp[] tcs = new ConnectionWithHttp[numThread];
		for (int i = 0; i < numThread; i++){
			ConnectionWithHttp tc = new ConnectionWithHttp(ulrs, step*i ,step*(i+1));
			tcs[i] = tc;
		}
		
		long start = System.currentTimeMillis();
		for (int i = 0; i < numThread; i++){
			tcs[i].start();
		}
		for (int i = 0; i < numThread; i++){
			try {
				tcs[i].join();
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		long end = System.currentTimeMillis();
		
		for (int i = 0; i < numThread; i++){
			tcs[i].disConnectAll();
		}
		
		System.out.println("Execution time was "+(end-start)+" ms...");
	}
	
	public void TestConnectionWithSocket(int numThread){
		ArrayList<String> ulrs = getURLs();
		int step = ulrs.size()/numThread;
		ConnectionWithSocket[] tcs = new ConnectionWithSocket[numThread];
		for (int i = 0; i < numThread; i++){
			ConnectionWithSocket tc = new ConnectionWithSocket(ulrs, step*i ,step*(i+1));
			tcs[i] = tc;
		}
		
		long start = System.currentTimeMillis();
		for (int i = 0; i < numThread; i++){
			tcs[i].start();
		}
		for (int i = 0; i < numThread; i++){
			try {
				tcs[i].join();
				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		long end = System.currentTimeMillis();
		
		
		System.out.println("Execution time was "+(end-start)+" ms.");
		System.gc();
	}
	
	
	private void TestConnectionTasks(){
		ArrayList<String> urls = getURLs();
		
		ArrayList<Runnable> taskArray = new ArrayList<Runnable>();
		for(int i = 0; i < 30 ; i ++){
			int ran = (int)Math.random()*urls.size();
			taskArray.add(new ConnectionTest(urls.get(i), i));
		}
		
		long start =0 ;
		long end =0 ;
		start = System.currentTimeMillis();
		for (int i = 0 ; i < taskArray.size(); i++){
			start(taskArray.get(i));
		}
		end = System.currentTimeMillis();
		System.out.println("Execution time was "+(end-start)+" ms.........");
	}
	
	
	private void TestConnectionWithExecutor(int numThread){
	
		ArrayList<String> urls = getURLs();
		ArrayList<Runnable> taskArray = new ArrayList<Runnable>();
		
		for (int i = 0; i <urls.size(); i++){
			Runnable task = new ConnectionTest(urls.get(i), i);
			taskArray.add(task);
		}
	//	ExecutorService conStarter = Executors.newFixedThreadPool(numThread);
		ExecutorService conStarter = Executors.newCachedThreadPool();
		long start = System.currentTimeMillis();
		for(int i=0; i<taskArray.size(); i++){
			conStarter.execute(taskArray.get(i));
		}
		conStarter.shutdown();
		try {
			conStarter.awaitTermination(1, TimeUnit.HOURS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		long end = System.currentTimeMillis();
		System.out.println("max threads : " + ((ThreadPoolExecutor)conStarter).getLargestPoolSize() );
		System.out.println("Execution time was "+(end-start)+" ms.........");
		System.gc();
	}
	
	private void start(Runnable task){
		task.run();
	}
	
	public void CheckServer(){
		ArrayList<String> ulrs = getURLs();
		Hashtable<InetAddress, ArrayList<String>> htable = new Hashtable<InetAddress, ArrayList<String>>();
		for(int i =0 ; i < ulrs.size() ; i++){
			try{
			
				
				InetAddress inetAdd = InetAddress.getByName(ulrs.get(i));
				
		//		System.out.println ("IP Address is : " + inetAdd.getHostAddress() + " " + ulrs.get(i));
				if(!htable.containsKey(inetAdd)){
					ArrayList<String> a = new ArrayList<String>(); a.add(ulrs.get(i));
					htable.put(inetAdd, a);
				}else {
					htable.get(inetAdd).add(ulrs.get(i));
				}
				
				
			}catch(Exception e){
				System.out.println(ulrs.get(i));
				e.printStackTrace();
			}
			
		}
		int i =0;
		for (InetAddress inetAdd : htable.keySet()) 
			if (htable.get(inetAdd).size() >1) {
				System.out.println(inetAdd); 
				
				i++;
		}
		
		System.out.println(i);
		System.out.println(htable.keySet().size());
	}
	
	// Extract websites from 1000 list
	private void writeFile(){
		BufferedReader br;
		BufferedWriter bw;
		try{
			br = new BufferedReader(new FileReader("top1000.txt"));
		
			PrintWriter pw = new PrintWriter(new FileWriter("top.txt"));
			String line;
			for(int i = 0 ; i < 1000; i++){
				line = br.readLine();
				if(line != null) {
					String[] tokens = line.split("\\s+");
					String web = "www." + tokens[2];
				//	System.out.println( web);
				}
				
			}
			
		}catch(IOException e){
			e.printStackTrace();
		}
		
		System.out.println("Done");
	}
	
	private ArrayList<String> getURLs(){
	//	return UrlFactory.getArrayUrls("top.txt", 1956);
		return UrlFactory.getArrayUrls("top.txt", 979);
	//	return UrlFactory.getArrayUrls("google", 200);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Experiment ex = new Experiment();
	//	ex.TestConnectionTasks();
	//	ex.start();
	//	ex.startThreadConnection(300);
	//	ex.startSocketThreadConnection(50);
		ex.TestConnectionWithExecutor(200);
	//	ex.CheckServer();
	//	ex.writeFile();
		ArrayList<String> urls = ex.getURLs();
		
		// Sample tasks for testing
		ArrayList<Runnable> taskArray = new ArrayList<Runnable>();
		
		for(int i = 0; i < 20 ; i ++){
			int ran = (int)Math.random()*urls.size();
			taskArray.add(new ConnectionTest(urls.get(ran), i));
		}
		
	//	MyPoolSizeCalculator pc = new MyPoolSizeCalculator();
		
	//	MyPoolSizeCalculator pc = new MyPoolSizeCalculator(20000);
		
	//	System.out.println(pc.calculateWithTesttime(new BigDecimal(1.0), (Collection)taskArray));
		
	//	System.out.println(pc.calculateWithoutTesttime(new BigDecimal(1.0), (Collection)taskArray));
		
	}
	
}
